/**
 * Software License, Version 1.0
 * 
 * Copyright 2003 The Trustees of Indiana University.  All rights reserved.
 * 
 *
 *Redistribution and use in source and binary forms, with or without 
 *modification, are permitted provided that the following conditions are met:
 *
 *1) All redistributions of source code must retain the above copyright notice,
 * the list of authors in the original source code, this list of conditions and
 * the disclaimer listed in this license;
 *2) All redistributions in binary form must reproduce the above copyright 
 * notice, this list of conditions and the disclaimer listed in this license in
 * the documentation and/or other materials provided with the distribution;
 *3) Any documentation included with all redistributions must include the 
 * following acknowledgement:
 *
 *"This product includes software developed by the Community Grids Lab. For 
 * further information contact the Community Grids Lab at 
 * http://communitygrids.iu.edu/."
 *
 * Alternatively, this acknowledgement may appear in the software itself, and 
 * wherever such third-party acknowledgments normally appear.
 * 
 *4) The name Indiana University or Community Grids Lab or NaradaBrokering, 
 * shall not be used to endorse or promote products derived from this software 
 * without prior written permission from Indiana University.  For written 
 * permission, please contact the Advanced Research and Technology Institute 
 * ("ARTI") at 351 West 10th Street, Indianapolis, Indiana 46202.
 *5) Products derived from this software may not be called NaradaBrokering, 
 * nor may Indiana University or Community Grids Lab or NaradaBrokering appear
 * in their name, without prior written permission of ARTI.
 * 
 *
 * Indiana University provides no reassurances that the source code provided 
 * does not infringe the patent or any other intellectual property rights of 
 * any other entity.  Indiana University disclaims any liability to any 
 * recipient for claims brought by any other entity based on infringement of 
 * intellectual property rights or otherwise.  
 *
 *LICENSEE UNDERSTANDS THAT SOFTWARE IS PROVIDED "AS IS" FOR WHICH NO 
 *WARRANTIES AS TO CAPABILITIES OR ACCURACY ARE MADE. INDIANA UNIVERSITY GIVES
 *NO WARRANTIES AND MAKES NO REPRESENTATION THAT SOFTWARE IS FREE OF 
 *INFRINGEMENT OF THIRD PARTY PATENT, COPYRIGHT, OR OTHER PROPRIETARY RIGHTS. 
 *INDIANA UNIVERSITY MAKES NO WARRANTIES THAT SOFTWARE IS FREE FROM "BUGS", 
 *"VIRUSES", "TROJAN HORSES", "TRAP DOORS", "WORMS", OR OTHER HARMFUL CODE.  
 *LICENSEE ASSUMES THE ENTIRE RISK AS TO THE PERFORMANCE OF SOFTWARE AND/OR 
 *ASSOCIATED MATERIALS, AND TO THE PERFORMANCE AND VALIDITY OF INFORMATION 
 *GENERATED USING SOFTWARE.
 */
package cgl.narada.service.fragmentation;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import cgl.narada.service.ServiceException;



public class FCTest {
  private String fragDirectory;
  private String fragExt = ".nbf";
  private String moduleName = "FCTest: ";
  
  public FCTest(String fragDirectory) {
    this.fragDirectory = fragDirectory;
  }
  
  
  public void 
  createAndStoreFragments(String largeFileLoc, int numOfFragments) 
    throws Exception {
    File largeFile = new File(largeFileLoc);
    if (!largeFile.exists()) {
      throw new ServiceException(moduleName + "File [" + largeFileLoc + 
				 "] does not exist!");
    }
    
    String filename = largeFile.getName();
    String fragDirLocation = fragDirectory + "\\" + filename + "-tempDir";
    long contentLength = largeFile.length();
    FileInputStream fis = new FileInputStream(largeFile);
    long totalWritten=0;
    
    int fragmentSize = (int) (contentLength/numOfFragments);
    int remaining = (int) ( contentLength - 
			(long)(numOfFragments*fragmentSize) );
    int lastFragmentSize = fragmentSize + remaining;

    int bytesRead = 0;
    for (int i = 1; i < numOfFragments; i++) {
      byte[] fragment = new byte[fragmentSize];
      bytesRead = fis.read(fragment);
      
      if (bytesRead != fragmentSize) {
	System.out.println(moduleName + "Tried to read (" + fragmentSize + 
			   ") bytes, ended up reading (" + bytesRead + 
			   ") bytes!");
      }
      writeIndividualFragment(fragDirLocation, i , fragment);
      totalWritten += fragmentSize;
    }/* end for */
    

    byte[] fragment = new byte[lastFragmentSize];
    bytesRead = fis.read(fragment);
    if (bytesRead != lastFragmentSize) {
      System.out.println(moduleName + "Tried to read (" + fragmentSize + 
			 ") bytes, ended up reading (" + bytesRead + 
			 ") bytes!");
    }
    
    writeIndividualFragment(fragDirLocation, numOfFragments, fragment);
    totalWritten += lastFragmentSize;

    fis.close();
    System.out.println(moduleName + "Total bytes written = " + totalWritten);
    
  }

   /** This method is used to write an individual fragment to the specified
      location. */
  private void writeIndividualFragment(String fragDirLocation, int fragmentNum,
				      byte[] fragment) 
    throws ServiceException {
    try {
      /** Make sure that the temporary fragmentation directory exists. If it
	  does not proceed to create the directory */
      File fragDirectory = new File(fragDirLocation);
      if (!fragDirectory.exists()) {
	fragDirectory.mkdirs();
      }
      
      /** Create the location of the fragmentation file that we would be
	  writing the fragment to */
      String fragFileName = 
	fragDirLocation + "\\fragment" + fragmentNum + fragExt;
      File fragFile = new File(fragFileName);
      fragFile.createNewFile();
      FileOutputStream fos = new FileOutputStream(fragFile);
      fos.write(fragment);
      fos.close();
    } catch (IOException ioe) {
      throw new ServiceException(moduleName + 
				 "Error in writeIndividualFragment()->" + ioe);
    }
  }


  public void createCoalescedFile(String filename, int numOfFragments) 
    throws Exception {
    String dirName = fragDirectory + "\\" + filename + "-tempDir";
    
    File dir = new File(dirName);
    String coalescedFileLocation = dir.getParent() + "\\C" + filename;
    
    File coalescedFile = new File(coalescedFileLocation);
    coalescedFile.createNewFile();
    FileOutputStream fos = new FileOutputStream(coalescedFile);
    
    for (int i=1; i <= numOfFragments; i++) {
      String fragFileName = dirName + "//fragment" + i + fragExt;
	
      File fragFile = new File(fragFileName);
      FileInputStream fis = new FileInputStream(fragFile);
      int willRead = (int)fragFile.length();
      byte[] fragment = new byte[willRead];
      int bytesActuallyRead = fis.read(fragment);
      if (willRead != bytesActuallyRead) {
	System.out.println(moduleName + "Tried to read (" + willRead + 
			   ") bytes. Ended up reading only (" + 
			   bytesActuallyRead + ") bytes");
      }
      
      fis.close();
      
      fos.write(fragment);
    } /* end totalNumberOfFragments */
    fos.close();
  }


  public static void main(String[] args) {
    try {
      FCTest fc = new FCTest("C:/TempFiles/tmpFiles/coalesce");
      String largeFileLoc = args[0];
      int numOfFragments = Integer.parseInt(args[1]);
      
      //for (int i=0; i< 50; i++) {
      //fc.createAndStoreFragments(largeFileLoc, numOfFragments);
      
      File largeFile = new File(largeFileLoc);
      String filename = largeFile.getName();
      //System.out.println("Coalescing ...");
      fc.createCoalescedFile(filename, numOfFragments);
      
      //String command = "diff filename a.cab";
      //Process p = Runtime.getRuntime().exec(command);
      //OutputStream out2 = p.getOutputStream();
      
      //System.out.println(out2);
      //}
    } catch (Exception e) {
      System.out.println(e);
    }
  }


}
